package com.example.common.utils;

import org.springframework.util.StringUtils;
import sun.net.util.IPAddressUtil;

import javax.servlet.http.HttpServletRequest;

public class RequestUtil {
    public static String getRealIP(HttpServletRequest request){
        //X-Real-IP nginx代理一般会加上此请求头
        String ip = request.getHeader("X-Real-IP");
        if(!StringUtils.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip)){
            return filterIp(ip);
        }
        //X-Forwarded-For 这是一个 Squid 开发的字段，只有在通过了HTTP代理或者负载均衡服务器时才会添加该项。　　　　
        //格式为X-Forwarded-For:client1,proxy1,proxy2，一般情况下，第一个ip为客户端真实ip，后面的为经过的代理服务器ip。现在大部分的代理都会加上这个请求头
        ip = request.getHeader("x-forwarded-for");
        if (!StringUtils.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值，第一个ip才是真实ip
            if(ip.contains(",")){
                ip = ip.split(",")[0];
                return filterIp(ip);
            }
        }
        ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        if (!StringUtils.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip)) {
            return filterIp(ip);
        }
        //Proxy-Client-IP/WL- Proxy-Client-IP ：这个一般是经过apache http服务器的请求才会有，
        // 用apache http做代理时一般会加上Proxy-Client-IP请求头，而WL-Proxy-Client-IP是他的weblogic插件加上的头
        ip = request.getHeader("Proxy-Client-IP");
        if (!StringUtils.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip)) {
            return filterIp(ip);
        }
        ip = request.getHeader("WL-Proxy-Client-IP");
        if (!StringUtils.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip)) {
            return filterIp(ip);
        }
        //HTTP_CLIENT_IP 有些代理服务器会加上此请求头
        ip = request.getHeader("HTTP_CLIENT_IP");
        if (!StringUtils.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip)) {
            return filterIp(ip);
        }
        ip = request.getRemoteAddr();
        return filterIp(ip);
    }

    public static boolean isPrivateIp(String ip){
        //tcp/ip协议中，专门保留了三个IP地址区域作为私有地址，其地址范围如下：
        //10.0.0.0/8：10.0.0.0～10.255.255.255
        //172.16.0.0/12：172.16.0.0～172.31.255.255
        //192.168.0.0/16：192.168.0.0～192.168.255.255
        if(ip.equals("0:0:0:0:0:0:0:1") || ip.equals("127.0.0.1")){
            return true;
        }
        byte[] addr = IPAddressUtil.textToNumericFormatV4(ip);
        return internalIp(addr);
    }

    private static boolean internalIp(byte[] addr) {
        final byte b0 = addr[0];
        final byte b1 = addr[1];
        //10.x.x.x/8
        final byte SECTION_1 = 0x0A;
        //172.16.x.x/12
        final byte SECTION_2 = (byte) 0xAC;
        final byte SECTION_3 = (byte) 0x10;
        final byte SECTION_4 = (byte) 0x1F;
        //192.168.x.x/16
        final byte SECTION_5 = (byte) 0xC0;
        final byte SECTION_6 = (byte) 0xA8;
        switch (b0) {
            case SECTION_1:
                return true;
            case SECTION_2:
                if (b1 >= SECTION_3 && b1 <= SECTION_4) {
                    return true;
                }
            case SECTION_5:
                if (b1 == SECTION_6) {
                    return true;
                }
            default:
                return false;
        }
    }

    private static String filterIp(String ip){
        if(IPAddressUtil.isIPv4LiteralAddress(ip)||IPAddressUtil.isIPv6LiteralAddress(ip)) return ip;
        return "INVALID IP:[" +ip+"]";
    }
}
